package com.xzcedu.regexp;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author 徐州城
 * @version 1.0
 * 分析java正则表达式的底层实现(重要.)
 */
public class RegTheory {
    public static void main(String[] args) {

        String content =
                "1998(20世纪90年代)，(3883)硬件领域出现了单片式计算机系统，这种价格低廉的系统一出现就立即引起了自动控制领域人员的注意，" +
                        "因为使用它可以大幅度提升消费类电子产品（如电视机顶盒、面包烤箱、移动电话等）的智能化程度。" +
                        "Sun公司为了抢占市场先机，在1991年成立了一个称为Green的项目小组，帕特里克、詹姆斯·高斯林、" +
                        "麦克·舍林丹和其他几个工程师一起组成的工作小组在加利福尼亚州门洛帕克市沙丘路的一个小工作室里面研" +
                        "究开发新技术，专攻计算机在家电产品上的嵌入式应用(1882)。";

        //目标: 匹配所有四个数字
        //说明
        //1. \\d 表示一个任意的数字
        String regStr = "(\\d\\d)(\\d\\d)";
        //2. 创建模式对象[即正则表达式对象]
        Pattern pattern = Pattern.compile(regStr);
        //3. 创建匹配器
        //说明: 创建匹配器matcher，按照 正则表达式的规则 去匹配 content字符串
        Matcher matcher = pattern.matcher(content);

        //开始匹配
        /**
         *
         * matcher.find() 完成的任务 (考虑分组)
         * 什么是分组，比如: (\d\d)(\d\d)，正则表达式中有() 表示分组，第1个()表示第1组，第2个()就是第2组
         * 1. 根据指定的规则，定位满足规则的子字符串(比如(19)(98))
         * 2. 找到后，将 子字符串的开始索引记录到 matcher对象的属性 int[] groups; 【例如 "减肥1234"，那么[0]=3 [1]=7】
         *      (2.1) groups[0] = 0, 把该子字符串的结束的索引记录下来+1的值记录到 groups[1] = 4
         *      (2.2) 记录第1组()匹配到底字符串 groups[2] = 0, groups[3] = 2
         *      (2.3) 记录第1组()匹配到底字符串 groups[4] = 2, groups[5] = 4
         *      (2.4) 如果有更多的分组依次类推
         * 3. 同时oldLast 的值为 子符串的结束的索引记录下来+1【即oldLast=groups[1]=4】，即下次执行find()时，就从4开始匹配
         *
         * matcher.group(0) 分析
         * 源码:
         * public String group(int group) {
         *         if (first < 0)
         *             throw new IllegalStateException("No match found");
         *         if (group < 0 || group > groupCount())
         *             throw new IndexOutOfBoundsException("No group " + group);
         *         if ((groups[group*2] == -1) || (groups[group*2+1] == -1))
         *             return null;
         *         return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();
         *     }
         *   (1) 根据 groups[0]=0 和 groups[1]=4 的记录位置，从content开始截取子字符串返回
         *       就是 [0, 4) 包含0但不包含索引为 4的位置
         *   (2) 如果再次执行 find()，仍然按照上面的分析来执行
         */
        while (matcher.find()){
            //小结
            //1. 如果正则表达式有() 即分组
            //2. 取出匹配的字符串规则如下
            //3. group(0) 表示匹配到的子字符串
            //4. group(1) 表示匹配到的子字符串第一组字串
            //5. group(2) 表示匹配到的子字符串第二组字串
            //6. 但是分组的数不能越界
            System.out.println("找到"+ matcher.group(0));//0表示整体，1表示第1组，2表示第2组
            System.out.println("第1组()匹配到的值=" + matcher.group(1));
            System.out.println("第2组()匹配到的值=" + matcher.group(2));
        }
    }
}


